package controller

import (
	"bytes"
	"context"
	"easyreport/conn"
	"easyreport/model"
	"encoding/csv"
	"encoding/gob"
	"fmt"
	"math"
	"net/http"
	"net/url"
	"regexp"
	"strconv"
	"strings"
	"time"

	"github.com/360EntSecGroup-Skylar/excelize/v2"
	"github.com/gin-gonic/gin"
	"github.com/go-xorm/xorm"
	"gopkg.in/iconv.v1"
)

var pingTime int64

type ReportController struct {
	Controller
}

func (m *ReportController) FindByHeader(c *gin.Context) {
	id := c.Param("id")
	dm := c.Param("dm")
	if !m.Auth(dm, c) {
		c.Abort()
		return
	}

	ret, err := conn.DB["def"].Query("select * from sys_reports where ID= ?", id+"")
	if err != nil {
		fmt.Println(err)
		c.JSON(http.StatusOK, gin.H{"code": "01", "msg": "查询失败！"})
		return
	}

	entity := DataToStruct(ret)[0]
	keys := entity.ColsEnName
	titles := entity.ColsTitle

	var item map[string]string
	var result []map[string]string
	for i, v := range keys {
		item = make(map[string]string)
		item["prop"] = v
		item["title"] = titles[i]
		result = append(result, item)
	}
	c.JSON(http.StatusOK, result)

}

func (m *ReportController) FindByList(c *gin.Context) {
	id := c.Param("id")
	dm := c.Param("dm")
	if !m.Auth(dm, c) {
		c.Abort()
		return
	}

	result, err := conn.DB["def"].Query("select * from sys_reports where ID= ?", id+"")
	if err != nil {
		fmt.Println(err)
		c.JSON(http.StatusOK, gin.H{"code": "01", "msg": "查询失败！"})
		return
	}

	entity := DataToStruct(result)[0]
	c.Request.ParseForm()

	filter := SqlFilter{entity: &entity}
	c.BindJSON(&filter.inParams)
	cur, _ := filter.inParams["cur"].(float64)
	size, _ := filter.inParams["size"].(float64)
	delete(filter.inParams, "cur")
	delete(filter.inParams, "size")
	filter.where()
	db := conn.DB[dm]
	if db == nil {
		db = conn.DB["def"]
	}
	filter.sqlParams[0] = `select count(1) MCOUNT from (` + strings.Replace(filter.entity.ExecSql, "$where", filter.sqlWhere.String(), -1) + `) `
	count, err := db.Query(filter.sqlParams...)
	if err != nil {
		fmt.Println(err)
		c.JSON(http.StatusOK, gin.H{"code": "02", "msg": "查询失败！"})
		return
	}
	str1 := `SELECT T.* FROM (SELECT T.*, ROWNUM RN FROM (`
	str2 := `) T WHERE ROWNUM <= ?) T WHERE RN > ?`
	filter.sqlParams[0] = str1 + strings.Replace(filter.entity.ExecSql, "$where", filter.sqlWhere.String(), -1) + str2
	filter.sqlParams = append(filter.sqlParams, cur*size)
	filter.sqlParams = append(filter.sqlParams, (cur-1)*size)

	mCount, _ := strconv.ParseUint(string(count[0]["MCOUNT"]), 10, 64)
	var ret []map[string]string
	if mCount > 0 {
		ret, err = db.QueryString(filter.sqlParams...)
		if err != nil {
			fmt.Println(err)
			c.JSON(http.StatusOK, gin.H{"code": "03", "msg": "查询失败！"})
			return
		}
	}
	c.JSON(http.StatusOK, gin.H{"code": "00200", "msg": "", "total": mCount, "data": ret})
}

func (m *ReportController) Download(c *gin.Context) {
	start := time.Now()

	id := c.Param("id")
	dm := c.Param("dm")
	if !m.Auth(dm, c) {
		c.Abort()
		return
	}
	result, err := conn.DB["def"].Query("select * from sys_reports where ID= ?", id+"")
	if err != nil {
		fmt.Println(err)
		c.JSON(http.StatusOK, gin.H{"code": "01", "msg": "获取报表信息失败！"})
		return
	}

	entity := DataToStruct(result)[0]
	c.Request.ParseForm()

	filter := SqlFilter{entity: &entity}
	c.BindJSON(&filter.inParams)
	filter.where()

	sql := conn.DB[dm]
	if sql == nil {
		sql = conn.DB["def"]
	}
	count := 0
	if entity.Type == ".txt" {
		countSql := "SELECT COUNT(1) as MCOUNT FROM (" + strings.Replace(filter.entity.ExecSql, "$where", filter.sqlWhere.String(), -1) + ")"
		filter.sqlParams[0] = countSql
		cdata, _ := sql.QueryString(filter.sqlParams...)
		count, _ = strconv.Atoi(string(cdata[0]["MCOUNT"]))
	}
	str1 := `SELECT T.* FROM (SELECT T.*, ROWNUM RN FROM (`
	str2 := `) T WHERE ROWNUM <= ?) T WHERE RN > ?`
	filter.sqlParams[0] = str1 + strings.Replace(filter.entity.ExecSql, "$where", filter.sqlWhere.String(), -1) + str2

	filter.sqlParams = append(filter.sqlParams, 2000)
	filter.sqlParams = append(filter.sqlParams, 0)
	cDate := time.Now().Format("20060102")
	c.Header("Content-Type", "application/octet-stream")
	if entity.Type == ".xlsx" {
		c.Header("Content-Disposition", fmt.Sprintf("attachment; filename=%s%s", url.QueryEscape(strings.Replace(entity.Name, "$date", cDate, 1)), ".xlsx"))
		m.createExcel(sql, c, &entity, filter.inParams, filter.sqlParams)
	} else if entity.Type == ".csv" {
		c.Header("Content-Disposition", fmt.Sprintf("attachment; filename=%s%s", url.QueryEscape(strings.Replace(entity.Name, "$date", cDate, 1)), ".csv"))
		m.createCsv(sql, c, &entity, filter.inParams, filter.sqlParams)
	} else if entity.Type == ".txt" {
		c.Header("Content-Disposition", fmt.Sprintf("attachment; filename=%s%s", url.QueryEscape(strings.Replace(entity.Name, "$date", cDate, 1)), ".TXT"))
		m.createTxt(sql, c, &entity, filter.inParams, filter.sqlParams, count)
	}
	c.Writer.CloseNotify()
	fmt.Println("总用时：", time.Since(start))
}

func (m *ReportController) createTxt(sql *xorm.Engine, c *gin.Context, entity *model.SysReports, p map[string]interface{}, params []interface{}, count int) error {
	var err error
	var tocode iconv.Iconv
	if entity.EnCode != "" {
		tocode, _ = iconv.Open(entity.EnCode, "UTF-8")
	}
	w := c.Writer
	if len(entity.FuncType) != 0 {
		w.WriteString(tocode.ConvString(entity.Name))
		w.WriteString("\n")

		if entity.Params != "" {
			w.WriteString(tocode.ConvString(entity.Params))
			w.WriteString("\n")
		}

		if len(entity.ColsTitle) != 0 {
			w.WriteString(tocode.ConvString(strings.Join(entity.ColsTitle, "|")))
			w.WriteString("\n")
		}
		w.Flush()
	}

	fmt.Print("请稍后")
	ctx := c.Request.Context()

	if strings.Contains(entity.Params, "$count_") {
		idx := strings.LastIndex(entity.Params, "$count_") + 7
		format := entity.Params[idx : idx+4]
		mcount := fmt.Sprintf(format, count)
		entity.Params = strings.Replace(entity.Params, "$count_"+format, mcount, 1)

	} else if strings.Contains(entity.Params, "$count") {
		mcount := strconv.Itoa(count)
		entity.Params = strings.Replace(entity.Params, "$count", mcount, 1)
	} else if strings.Contains(entity.Params, "$date") {
		cDate := time.Now().Format("20060102")
		entity.Params = strings.Replace(entity.Params, "$date", cDate, 1)
	}
	w.WriteString(entity.Params)
	w.WriteString("\n")
	w.Flush()

	limit := params[len(params)-2].(int)
	var data []map[string]string

	for {
		if !cliIsConn(ctx) {
			return nil
		}
		fmt.Println(params)
		data, err = sql.QueryString(params...)
		if err != nil {
			fmt.Println("获取数据", err)
			return nil
		}

		dataSize := len(data)
		var line []string
		for _, m := range data {
			if !cliIsConn(ctx) {
				return nil
			}
			line = []string{}
			for _, k := range entity.ColsEnName {
				if !cliIsConn(ctx) {
					return nil
				}
				val := m[k]
				line = append(line, val)
			}
			w.WriteString(tocode.ConvString(strings.Join(line, "|")))
			w.WriteString("\n")
		}
		w.Flush()
		if dataSize < limit {
			break
		} else {
			params[len(params)-1] = params[len(params)-1].(int) + dataSize
			params[len(params)-2] = params[len(params)-2].(int) + dataSize
		}
	}
	return nil
}

func (m *ReportController) createCsv(sql *xorm.Engine, c *gin.Context, entity *model.SysReports, p map[string]interface{}, params []interface{}) error {
	if entity.EnCode == "" {
		c.Writer.Write([]byte("\xEF\xBB\xBF"))
	}
	var err error
	var tocode iconv.Iconv
	if entity.EnCode != "" {
		tocode, _ = iconv.Open(entity.EnCode, "UTF-8")
	}
	w := csv.NewWriter(c.Writer)
	line := []string{entity.Name}
	if entity.EnCode != "" {
		for i, v := range line {
			line[i] = tocode.ConvString(v)
		}
	}
	w.Write(line)

	if entity.Params != "" {
		line := []string{entity.Params}
		if entity.EnCode != "" {
			for i, v := range line {
				line[i] = tocode.ConvString(v)
			}
		}
		w.Write(line)
	}
	if len(entity.ColsTitle) != 0 {
		line := entity.ColsTitle
		if entity.EnCode != "" {
			for i, v := range line {
				line[i] = tocode.ConvString(v)
			}
		}
		w.Write(line)
	}
	w.Flush()

	limit := params[len(params)-2].(int)
	var data []map[string]string
	funcs := make([]string, len(entity.ColsEnName))
	funcs[0] = "统计"

	fmt.Printf("报表名称[%s]\n", entity.Name)
	fmt.Print("请稍后")
	ctx := c.Request.Context()
	for {
		if !cliIsConn(ctx) {
			return nil
		}
		data, err = sql.QueryString(params...)
		if err != nil {
			fmt.Println(err)
			return nil
		}

		dataSize := len(data)
		var lines [][]string
		var line []string
		for _, m := range data {
			if !cliIsConn(ctx) {
				return nil
			}
			line = []string{}
			for i, k := range entity.ColsEnName {
				if !cliIsConn(ctx) {
					return nil
				}
				val := m[k]
				/*pattern := "\\d{" + strconv.Itoa(len(val)) + "}"
				flag, _ := regexp.MatchString(pattern, val)
				if flag {
					val = val + "\t"
				}*/
				if entity.EnCode != "" {
					val = tocode.ConvString(val)
				}
				line = append(line, val)

				for _, v := range entity.FuncType {
					if !cliIsConn(ctx) {
						return nil
					}
					val := m[k]
					switch v {
					case "MAX(" + k + ")":
						maxVal, _ := strconv.ParseFloat(val, 64)
						minVal, _ := strconv.ParseFloat(funcs[i], 64)
						funcs[i] = strconv.FormatFloat(math.Max(minVal, maxVal), 'f', -1, 64)
					case "SUM(" + k + ")":
						maxVal, _ := strconv.ParseFloat(val, 64)
						minVal, _ := strconv.ParseFloat(funcs[i], 64)
						funcs[i] = strconv.FormatFloat(minVal+maxVal, 'f', 6, 64)
					case "MIN(" + k + ")":
						maxVal, _ := strconv.ParseFloat(val, 64)
						if funcs[i] == "" {
							funcs[i] = val
						}
						minVal, _ := strconv.ParseFloat(funcs[i], 64)
						funcs[i] = strconv.FormatFloat(math.Min(minVal, maxVal), 'f', -1, 64)
					}
				}
			}
			lines = append(lines, line)
		}
		w.WriteAll(lines)
		w.Flush()
		fmt.Print(".")
		if dataSize < limit {
			break
		} else {
			params[len(params)-1] = params[len(params)-1].(int) + dataSize
			params[len(params)-2] = params[len(params)-2].(int) + dataSize
		}
	}
	if len(entity.FuncType) != 0 {
		w.Write(funcs)
		w.Flush()
	}
	return nil
}

func (m *ReportController) createExcel(sql *xorm.Engine, c *gin.Context, entity *model.SysReports, p map[string]interface{}, params []interface{}) {
	file := excelize.NewFile()
	file.SetSheetName("Sheet1", entity.Name)
	file.SetDefaultFont("黑体")
	row := 1
	hCell := "A1"
	vCell := CellName(len(entity.ColsEnName), 1)
	//标题设置
	style, _ := file.NewStyle(`{"alignment":{"horizontal":"left","vertical":"center"},"color":["#C7EECF"],
		"border":[{"type":"left","color":"5b6369","style":1},
		{"type":"top","color":"5b6369","style":1},
		{"type":"bottom","color":"5b6369","style":1},
		{"type":"right","color":"5b6369","style":1}],
		"font":{"bold":true,"size":16},
		"fill":{"type":"pattern","color":["#a6a6a6"],"pattern":1}}`)
	file.SetCellStyle(entity.Name, hCell, vCell, style)
	file.MergeCell(entity.Name, hCell, vCell)
	file.SetCellValue(entity.Name, hCell, entity.Name)
	file.SetRowHeight(entity.Name, 1, 30)
	//endcol, _ := excelize.ColumnNumberToName(len(entity.ColsEnName))
	//file.SetColWidth(entity.Name, "A", endcol, 20)

	//自定义参数设置
	if len(p) != 0 {
		style, _ := file.NewStyle(`{"border":[{"type":"left","color":"5b6369","style":1},
		{"type":"top","color":"5b6369","style":1},
		{"type":"bottom","color":"5b6369","style":1},
		{"type":"right","color":"5b6369","style":1}],
		"font":{"size":12,"color":"303337","bold":true}}`)
		row++
		file.MergeCell(entity.Name, CellName(1, row), CellName(len(entity.ColsEnName), row))
		file.SetCellStyle(entity.Name, CellName(1, row), CellName(len(entity.ColsEnName), row), style)
		file.SetCellValue(entity.Name, CellName(1, row), entity.Params)
	}

	if len(entity.GroupTitle) != 0 {
		row++
		file.SetCellStyle(entity.Name, CellName(1, row), CellName(len(entity.ColsEnName), row), style)

		style, _ = file.NewStyle(`{"alignment":{"horizontal":"center","vertical":"center"},"color":["#C7EECF"],
		"border":[{"type":"left","color":"5b6369","style":1},
		{"type":"top","color":"5b6369","style":1},
		{"type":"bottom","color":"5b6369","style":1},
		{"type":"right","color":"5b6369","style":1}],
		"font":{"bold":true,"size":13},
		"fill":{"type":"pattern","color":["#a6a6a6"],"pattern":1}}`)

		for _, v := range entity.GroupTitle {
			obj := strings.Split(v, "|")
			name := obj[0]
			start := 0
			end := 0
			for j, d := range entity.ColsTitle {
				if d == obj[1] {
					start = j
				} else if d == obj[2] {
					end = j
				}
			}
			/*for i := 0; i <= len(entity.ColsTitle); i++ {
				if i <= start || i > end {
					file.MergeCell(entity.Name, excelize.ToAlphaString(i)+strconv.Itoa(row), excelize.ToAlphaString(i)+strconv.Itoa(row+1))
				}
			}*/
			hCell := CellName(start+1, row)
			vCell := CellName(end+1, row)
			file.MergeCell(entity.Name, hCell, vCell)
			file.SetCellValue(entity.Name, hCell, name)
		}
		file.SetCellStyle(entity.Name, CellName(1, row), CellName(len(entity.ColsEnName), row), style)
	}

	//函数行设置
	var funcIndex int
	if len(entity.FuncType) != 0 {
		style, _ := file.NewStyle(`{"border":[{"type":"left","color":"3299CC","style":3},
		{"type":"top","color":"3299CC","style":3},
		{"type":"bottom","color":"3299CC","style":3},
		{"type":"right","color":"3299CC","style":3}],
		"font":{"size":14,"color":"FF0000","bold":false}}`)
		row++
		funcIndex = row
		file.SetCellStyle(entity.Name, CellName(1, row), CellName(len(entity.ColsEnName), row), style)
		file.SetCellValue(entity.Name, CellName(1, row), "统计")
	}

	//表头设置
	row++
	style, _ = file.NewStyle(`{"border":[{"type":"left","color":"5b6369","style":1},
		{"type":"top","color":"5b6369","style":1},
		{"type":"bottom","color":"5b6369","style":1},
		{"type":"right","color":"5b6369","style":1}],
		"font":{"bold":true,"size":12,"color":"303337"},
		"fill":{"type":"pattern","color":["#bfbfbf"],"pattern":1}}`)
	file.SetCellStyle(entity.Name, CellName(1, row), CellName(len(entity.ColsEnName), row), style)

	file.SetCellValue(entity.Name, "A"+strconv.Itoa(row), "序号")

	for i, v := range entity.ColsTitle {
		file.SetCellValue(entity.Name, CellName(i+1, row), v)
	}

	//数据设置
	style, _ = file.NewStyle(`{"border":[{"type":"left","color":"5b6369","style":1},
		{"type":"top","color":"5b6369","style":1},
		{"type":"bottom","color":"5b6369","style":1},
		{"type":"right","color":"5b6369","style":1}],
		"font":{"size":12,"color":"303337"}}`)

	row++
	var data []map[string]interface{}
	var err error
	limit := params[len(params)-2].(int)
	dataIndex := 0
	funcs := make([]float64, len(entity.ColsEnName))
	fmt.Println("正在下载")
	heights := make([]float64, len(entity.ColsEnName))
	ctx := c.Request.Context()
	for {
		if !cliIsConn(ctx) {
			return
		}
		data, err = sql.QueryInterface(params...)
		if err != nil {
			fmt.Println(err)
			return
		}
		dataSize := len(data)

		for _, m := range data {
			if !cliIsConn(ctx) {
				return
			}
			dataIndex++
			file.SetCellValue(entity.Name, "A"+strconv.Itoa(row), strconv.Itoa(dataIndex))
			for i, k := range entity.ColsEnName {
				if !cliIsConn(ctx) {
					return
				}

				file.SetCellValue(entity.Name, CellName(i+1, row), m[k])
				size := GetLen(m[k])
				heights[i] = math.Max(size, heights[i])

				for _, v := range entity.FuncType {
					if !cliIsConn(ctx) {
						return
					}
					val := m[k]
					if val == nil {
						continue
					}
					switch v {
					case "MAX(" + k + ")":
						funcs[i] = math.Max(funcs[i], vType(val))
					case "SUM(" + k + ")":
						funcs[i] = funcs[i] + vType(val)
					case "MIN(" + k + ")":
						if funcs[i] == 0 {
							funcs[i] = vType(val)
						}
						funcs[i] = math.Min(vType(val), funcs[i])
					}
				}
			}
			file.SetCellStyle(entity.Name, CellName(1, row), CellName(len(entity.ColsEnName), row), style)
			row++
		}

		if dataSize < limit {
			break
		} else {
			params[len(params)-1] = params[len(params)-1].(int) + dataSize
			params[len(params)-2] = params[len(params)-2].(int) + dataSize
			fmt.Printf("下载中.第%d至%d\n", params[len(params)-1], params[len(params)-2])
		}
	}
	for i, v := range heights {
		col, _ := excelize.ColumnNumberToName(i + 1)
		file.SetColWidth(entity.Name, col, col, v)
	}
	for i, v := range funcs {
		if v == 0 {
			continue
		}
		file.SetCellValue(entity.Name, CellName(i+1, funcIndex), v)
	}
	file.WriteTo(c.Writer)
}

func cliIsConn(ctx context.Context) bool {
	select {
	case <-ctx.Done():
		fmt.Println("客户端已断开")
		return false
	default:
		return true
	}
	return true
}

type SqlFilter struct {
	entity    *model.SysReports
	inParams  map[string]interface{}
	sqlWhere  strings.Builder
	sqlParams []interface{}
}

func (m *SqlFilter) where() {
	m.sqlParams = append(m.sqlParams, m.entity.ExecSql)
	m.sqlToIF()
	m.whereToIF()
	m.sqlToWheres()
	for k, v := range m.inParams {
		if v != nil {
			m.pWhere(k, v)
			if strings.Contains(m.entity.Params, k) {
				m.entity.Params = strings.Replace(m.entity.Params, k, v.(string), 1)
			}
		}
	}
}

func (m *SqlFilter) pWhere(k string, v interface{}) {
	for _, sv := range m.entity.SqlWhere {
		if strings.Contains(sv, "if ?"+k) {
			continue
		}
		i := strings.Index(sv, "?"+k)
		if i == -1 {
			i = strings.Index(sv, "?%"+k)
		}
		if i != -1 {
			vv, ok := v.([]interface{})
			if ok { //in条件
				m.sqlWhere.WriteString(strings.Replace(sv, "?"+k, inWhere(len(vv)), -1))
				for _, d := range vv {
					m.sqlParams = append(m.sqlParams, d)
				}
			} else {
				vv, _ := v.(string)
				if vv == "" {
					continue
				}
				var like = ""
				if strings.Contains(sv, "%") {
					like = "%"
					m.sqlWhere.WriteString(strings.Replace(sv, "?%"+k+"%", "? ", -1))
				} else {
					m.sqlWhere.WriteString(strings.Replace(sv, "?"+k, "? ", -1))
				}
				m.sqlParams = append(m.sqlParams, like+strings.TrimSpace(vv)+like)
				m.entity.Params = strings.Replace(m.entity.Params, k, vv, -1)
			}
		}
	}
}

func (m *SqlFilter) sqlToWheres() {
	pmax := strings.Count(m.entity.ExecSql, "?")
	reg := regexp.MustCompile(`\?\w+`)
	for i := 0; i < pmax; i++ {
		result := reg.FindString(m.entity.ExecSql)
		fmt.Println(result)
		if result == "" {
			continue
		}
		k := result[1:]
		v := m.inParams[k]
		vv, ok := v.([]interface{})
		if ok { //in条件
			m.entity.ExecSql = strings.Replace(m.entity.ExecSql, "?"+k, inWhere(len(vv)), 1)
			for _, d := range vv {
				m.sqlParams = append(m.sqlParams, d)
			}
		} else {
			m.entity.ExecSql = strings.Replace(m.entity.ExecSql, result, "? ", 1)
			vv, _ := v.(string)
			m.sqlParams = append(m.sqlParams, strings.TrimSpace(vv))
			m.entity.Params = strings.Replace(m.entity.Params, k, vv, 1)
		}
	}
}

func (m *SqlFilter) sqlToIF() {
	for k, v := range m.inParams {
		fid := "if ?" + k
		count := strings.Count(m.entity.ExecSql, fid)
		for i := 0; i < count; i++ {
			if strings.Contains(m.entity.ExecSql, fid) {
				startV := strings.Index(m.entity.ExecSql, "==") + 2
				flag := true
				if startV == 1 {
					flag = false
					startV = strings.Index(m.entity.ExecSql, "!=") + 2
				}
				endV := strings.Index(m.entity.ExecSql, "{")
				sqlV := strings.TrimSpace(m.entity.ExecSql[startV:endV])

				if (sqlV == v) == flag {
					end := strings.Index(m.entity.ExecSql, "}")
					sql := m.entity.ExecSql[endV+1 : end]
					if strings.Contains(sql, "[") && strings.Contains(sql, "]") {
						ftable := strings.Split(sql[strings.Index(sql, "[")+1:strings.Index(sql, "]")], ",")
						for i := 0; i < len(ftable); i++ {
							intime, _ := time.Parse("20060102", v.(string)[:8])
							day := int(time.Now().Sub(intime).Hours() / 24)
							kv := strings.Split(ftable[i], "-")
							max, _ := strconv.Atoi(kv[0])
							if i == len(ftable)-1 || day <= max {
								sql = kv[1]
								break
							}
						}
					}
					start := strings.Index(m.entity.ExecSql, fid)
					m.entity.ExecSql = strings.Replace(m.entity.ExecSql, m.entity.ExecSql[start:end+1], sql, 1)
				}
			}
		}
	}
}

func (m *SqlFilter) whereToIF() {
	for k, v := range m.inParams {
		if v != nil {
			for i, sv := range m.entity.SqlWhere {
				fid := "if ?" + k
				if strings.HasPrefix(sv, fid) {
					startV := strings.Index(sv, "==") + 2
					flag := true
					if startV == 1 {
						flag = false
						startV = strings.Index(sv, "!=") + 2
					}

					endV := strings.Index(sv, "{")
					if (strings.TrimSpace(sv[startV:endV]) == v) == flag {
						sql := sv[endV+1 : strings.Index(sv, "}")]
						if strings.Contains(sql, "?") {
							m.entity.SqlWhere[i] = sql
						} else {
							m.sqlWhere.WriteString(sql)
						}
					}
				}
			}
		}
	}
}

func CellName(col, row int) string {
	colIndex, err := excelize.CoordinatesToCellName(col, row)
	if err != nil {
		fmt.Println(err)
	}
	return colIndex
}
func vType(v interface{}) float64 {
	switch v.(type) {
	case float64:
		return v.(float64)
	case int64:
		return float64(v.(int64))
	case string:
		val := strings.Replace(v.(string), " ", "", -1)
		if val == "" {
			return 0
		}
		ret, err := strconv.ParseFloat(val, 64)
		if err != nil {
			panic(err)
		}
		return ret
	}
	return 0
}

func GetLen(key interface{}) float64 {
	var buf bytes.Buffer
	enc := gob.NewEncoder(&buf)
	err := enc.Encode(key)
	if err != nil {
		return 0
	}
	l := len(buf.Bytes())
	if l < 12 {
		return 12
	} else if l >= 50 {
		return 50
	}
	return float64(l)
}
